package com.example.tongyao.system.controller;

import com.example.tongyao.system.entity.SysUser;
import com.example.tongyao.utils.DataResult;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.http.HttpStatus;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;

/**
 * 用户登录认证
 *
 * @version 1.0
 * @author tongyao
 * @since 2020-06-13
 */
@RestController
@Api(tags = "系统 - 登录认证")
public class AuthController {

    @Autowired
    DefaultKaptcha defaultKaptcha;

    /**
     * 登录接口
     * @param username
     * @param password
     * @return
     */
    @ApiOperation(
            value = "登录认证",
            notes = "登录认证",
            httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username",value = "账号",required = true),
            @ApiImplicitParam(name = "password",value = "密码",required = true)
    })
    @PostMapping(value = "/login" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult login(String username,String password,
                            HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) {
        //开始校验验证码
        String captchaId = (String) httpServletRequest.getSession().getAttribute("tongYaoVrifyCode");
        String parameter = httpServletRequest.getParameter("vrifyCode");
        System.out.println("Session里的验证码为："+captchaId+" 浏览器输入的验证码为："+parameter);

        if (!parameter.equals(captchaId)) {
            return DataResult.setResult(401,"验证码不正确！");
        }

        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            SysUser user = (SysUser) subject.getPrincipal();
            if(user.getStatus() != true){
                return DataResult.setResult(HttpStatus.SC_ACCEPTED,"该账户禁止登录！");
            }

            if(user.getSysRole().getRoleStatus() != true){
                return DataResult.setResult(HttpStatus.SC_ACCEPTED,"该账户角色未开放，请联系管理员！");
            }

            if(user.getSysRole().getDelFlag() != true){
                return DataResult.setResult(HttpStatus.SC_ACCEPTED,"该角色已删除！请联系管理员重新分配。");
            }

            //存储sessionId
            user.setSessionId(subject.getSession().getId()+"");
            return DataResult.setResult(user);
        }catch (Exception e) {
            return DataResult.setResult(HttpStatus.SC_ACCEPTED,"账号或密码错误！");
        }
    }

    /**
     * 退出登录
     * @return
     */
    @ApiOperation(
            value = "退出登录",
            notes = "退出登录",
            httpMethod = "Get")
    @GetMapping("/logout")
    public DataResult logout() {
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            subject.logout();
        }
        return DataResult.setSuccess(true);
    }

    @ApiOperation(
            value = "获取验证码",
            notes = "获取验证码",
            httpMethod = "Get")
    @GetMapping("/getVrifyCode")
    public void getVrifyCode(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception{
        byte[] captchaChallengeAsJpeg = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try {
            //生产验证码字符串并保存到session中
            String createText = defaultKaptcha.createText();
            httpServletRequest.getSession().setAttribute("tongYaoVrifyCode", createText);

            //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        //定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream =
                httpServletResponse.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
    }

    /**
     * 大厂都在用的邮箱、短信6位验证码，并且带有效时间和失效时间，不得不说Session真是好玩意儿，就是前端的本地存储
     * @param request
     * @return
     */
    @GetMapping("/code")
    public String code(HttpServletRequest request){
        HttpSession session = request.getSession();
        long result = 0;
        if(session.getAttribute("date") != null){
            result = (System.currentTimeMillis() / 1000) - Long.parseLong(session.getAttribute("date").toString());
        }
        System.out.println("当前验证已过："+result+"秒");
        String code = "";
        if(session.getAttribute("date") == null || result >= 60){
            for (int i = 0; i < 6; i++) {
                code += new Random().nextInt(10);
            }
            // 验证码
            session.setAttribute("code",code);

            // 生成时间
            session.setAttribute("date",System.currentTimeMillis() / 1000);
            return "您的验证码是："+code;
        }

        return "有效期60秒，验证还在有效期！";
    }
    @GetMapping("/verify")
    public String verify(HttpServletRequest request,String code){
        HttpSession session = request.getSession();
        if(session.getAttribute("date") != null){
            long result = (System.currentTimeMillis() / 1000) - Long.parseLong(session.getAttribute("date").toString());
            System.out.println("算出来的result："+result);
            if(result <= 60){
                if(session.getAttribute("code").toString().equals(code)){
                    return "验证码正确！";
                }else{
                    return "验证码不正确！";
                }
            }else{
                return "验证码已过期！请重新获取！";
            }
        }
        return "未获取验证码！";
    }
}
